
/*-----------------------------------------------------------------------
 * Copyright (C) 2001 Green Light District Team, Utrecht University 
 *
 * This program (Green Light District) is free software.
 * You may redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by
 * the Free Software Foundation (version 2 or later).
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * See the documentation of Green Light District for further information.
 *------------------------------------------------------------------------*/

package gld.algo.tlc;
/** This class can be used to create instances of Traffic Light Controllers
  * for a specific infrastructure.
 */

import gld.algo.haluk.TLCHaluk;
import gld.algo.park.BasicTLC;
import gld.infra.InfraException;
import gld.infra.Infrastructure; 
import gld.utils.StringUtils;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Random;
 
public class TLCFactory
{
	protected Infrastructure infra;
	protected Random random;

	protected static final int			
		RANDOM=0,         		
 		LONGEST_QUEUE=1,  		
		MOST_CARS=2,	      			
		TC_1=3,      			
		TC_2=4,				
		TC_3=5,       			
		ACGJ_1=6,	      				
		ACGJ_2=7,	      				 
		ACGJ_3=8,	      				
		BEST_FIRST=9,					
		RELATIVE_LONGEST_QUEUE=10, 
		RLD=11,				
		TC_1OPT=12,							
		TC_2OPT=13,							
		LOCAL=14,							
		GENNEURAL=15,						
		ACGJ_3_FV=16,				
		RLD2=17,
		IATRACOS=18,
		MOREVTS_MARCHING=19,
		MOREVTS_OPTIM=20,
		MOREVTS_COUNTING_CARS=21,
		MOREVTS_COUNTING_CARS2=22,
		MOREVTS_SOTL_REQUEST=23,
		MOREVTS_SOTL_PHASE=24,
		MOREVTS_SOTL_PLATOON=25,
		MOREVTS_OPTIM_WETSTRAAT=26,
		MOREVTS_MARCHING_WETSTRAAT=27,
		MOREVTS_SOTL_PLATOON2=28,
		MOREVTS_OPTIM_LONGCLEAR=29,
		CU_OPTIM=30,
		CU_SOTL_P = 31,
		CU_COFIELDS = 32,
		CU_WIRELESS_SENSOR = 33,
		CU_TC1 = 34,
		BASIC_TLC = 35,
		HALUK_1 = 36;
	
		
		
		
	protected static final String[] tlcDescs = {
		"Random",
		"Longest Queue",
		"Most Cars",
		"TC-1",
		"TC-2",
		"TC-3",
		"ACGJ-1",
		"ACGJ-2",
		"ACGJ-3",
		"Best First",
		"Relative Longest Queue",
		"Red Light District",
		"TC-1 Speed Optimized",
		"TC-2 Speed Optimized",
		"Local Hillclimbing",
		"GenNeural",
		"ACGJ-3 Stupidified",
		"Red Light District 2",
		"iAtracos",
		"Marching control",
		"Optim control",
		"Self organizing: counting cars",
		"Self organizing: counting cars with minimal phase",
		"Sotl Request Control",
		"Sotl Phase Control",
		"Sotl Platoon Control",
		"Optim control for Wetstraat",
		"Marching control for Wetstraat",
		"Sotl Platoon Controller 2",
		"Optim control with long clearance time",
		"Optim control for CU",
		"Sotl Platoon for CU", 
		"Co-Fields for CU",
		"Wireless Sensor for CU",
		"TC-1 for CU"
	};
	
	protected static final String[] xmlNames = {
		RandomTLC.shortXMLName,
		LongestQueueTLC.shortXMLName,
		MostCarsTLC.shortXMLName,
		TC1TLC.shortXMLName,
		TC2TLC.shortXMLName,
		TC3TLC.shortXMLName,
		ACGJ1.shortXMLName,
		ACGJ2.shortXMLName,
		ACGJ3.shortXMLName,
		BestFirstTLC.shortXMLName,
		RelativeLongestQueueTLC.shortXMLName,
		RLDTLC.shortXMLName,
		TC1TLCOpt.shortXMLName,
		TC2TLCOpt.shortXMLName,
		LocalHillTLC.shortXMLName,
		GenNeuralTLC.shortXMLName,
		ACGJ3FixedValue.shortXMLName,
		RLD2TLC.shortXMLName,
		IATRACOSTLC.shortXMLName,
		MorevtsMarchingTLC.shortXMLName,
		MorevtsOptimTLC.shortXMLName,
		MorevtsCountingCars.shortXMLName,
		MorevtsCountingCars2.shortXMLName,
		MorevtsSotlRequest.shortXMLName,
		MorevtsSotlPhase.shortXMLName,
		MorevtsSotlPlatoon.shortXMLName,
		MorevtsOptimWetstraatTLC.shortXMLName,
		MorevtsMarchingWetstraatTLC.shortXMLName,
		MorevtsSotlPlatoon2.shortXMLName,
		MorevtsOptimLongClear.shortXMLName,
		BroadwayOptim.shortXMLName,
		BroadwaySotlPlatoon.shortXMLName, 
		BroadwayCoFields.shortXMLName,
		BroadwayWirelessSensor.shortXMLName,
		BroadwayTC1.shortXMLName
	};
		
		
	protected static final String[] categoryDescs = 
	{
		"INTEL_TRANS",
		"MoreVTS" ,
		"Simple Maths", 
		"Complex Maths", 
		"Longest Q-variants", 
		"Reinforcement Learning", 
		"Genetic", 
		"Neural Network",
	};
	protected static final int[][] categoryTLCs = {
		//0
		{CU_SOTL_P, CU_OPTIM, CU_COFIELDS, CU_WIRELESS_SENSOR, CU_TC1},
		{MOREVTS_MARCHING, MOREVTS_OPTIM, MOREVTS_COUNTING_CARS, MOREVTS_COUNTING_CARS2, MOREVTS_SOTL_REQUEST, MOREVTS_SOTL_PHASE, MOREVTS_SOTL_PLATOON, 
			MOREVTS_OPTIM_WETSTRAAT, MOREVTS_MARCHING_WETSTRAAT, MOREVTS_SOTL_PLATOON2, MOREVTS_OPTIM_LONGCLEAR} ,
		{RANDOM, MOST_CARS, RLD, RLD2, IATRACOS},
		{LOCAL, ACGJ_2},
		{LONGEST_QUEUE, RELATIVE_LONGEST_QUEUE, BEST_FIRST},
		{ TC_1, TC_2, TC_3, TC_1OPT, TC_2OPT },
		{ACGJ_1, ACGJ_3, ACGJ_3_FV},
		{GENNEURAL},
		//8 - PARK
		{BASIC_TLC},
		//9 - HALUK
		{HALUK_1},
	};

	/** Makes a new TLCFactory for a specific infrastructure with a new
	  * random number generator.
	  * @param infra The infrastructure
	 */
  	public TLCFactory(Infrastructure infra)
	{ 	this.infra=infra;
		random=new Random();
	}
  
	/** Makes a new TLCFactory for a specific infrastructure 
	  * @param random The random number generator which some algorithms use
	  * @param infra The infrastructure
	 */
  	public TLCFactory(Infrastructure infra, Random random)
  	{ 	this.infra=infra;
		this.random=random;
  	}
  
	/** Looks up the id of a TLC algorithm by its description
	  * @param algoDesc The description of the algorithm
	  * @returns The id of the algorithm
	  * @throws NoSuchElementException If there is no algorithm with that
	  *        description.
	 */
	public static int getId (String algoDesc)
	{ 	return StringUtils.getIndexObject(tlcDescs,algoDesc);
	}
	
	/** Returns an array of TLC descriptions */
	public static String[] getTLCDescriptions() { return tlcDescs; }
  
  	/** Look up the description of a TLC algorithm by its id 
	  * @param algoId The id of the algorithm
	  * @returns The description
	  * @throws NoSuchElementException If there is no algorithm with the
	  *	    specified id.
	*/
  	public static String getDescription (int algoId)
  	{ 	return (String)(StringUtils.lookUpNumber(tlcDescs,algoId));
  	}
  
  	/** Returns an array containing the TLC category descriptions. */
  	public static String[] getCategoryDescs() 
	{ 	return categoryDescs; 
	}
	
  	/** Returns an array of TLC numbers for each TLC category. */
  	public static int[][] getCategoryTLCs() 
	{ 	return categoryTLCs; 
	}
	
  	/** Returns the total number of TLCs currently available. */
 	public static int getNumberOfTLCs() 
	{ 	return tlcDescs.length; 
	}

  	/** Gets the number of an algorithm from its XML tag name */
  	public int getNumberByXMLTagName(String tagName) 
  	{ 	return StringUtils.getIndexObject(xmlNames,tagName);
  	}
  
  	/** Returns an instance of a TLC by its description. */
  	public TLController genTLC (String tlcDesc) throws InfraException
	{	return getInstanceForLoad(getId(tlcDesc));
	}
	
	public TLController genTLC(int cat, int tlc) throws InfraException
	{
		return getInstanceForLoad(categoryTLCs[cat][tlc]);
	}
  
  	/** Gets a new instance of an algorithm by its number. This method
    	  * is meant to be used for loading.
   	*/
	public TLController getInstanceForLoad (int algoId) throws InfraException
	{
		switch (algoId)
	    	{ 	case RANDOM : //throw new InfraException("This controller is not supported:"+algoId); //
	    	return (random != null ? new RandomTLC(infra, random): new RandomTLC(infra));
			case LONGEST_QUEUE : //throw new InfraException("This controller is not supported:"+algoId); //
			return new LongestQueueTLC(infra);
			case TC_1 : //throw new InfraException("This controller is not supported:"+algoId); //
			return new TC1TLC(infra);
			case TC_2 : //throw new InfraException("This controller is not supported:"+algoId); //
				return new TC2TLC(infra);
			case TC_3 : //throw new InfraException("This controller is not supported:"+algoId); //
				return new TC3TLC(infra);
			case ACGJ_1 : //throw new InfraException("This controller is not supported:"+algoId); //
				return new ACGJ1(infra);		
			case ACGJ_2 : //throw new InfraException("This controller is not supported:"+algoId); //
				return new ACGJ2(infra);
			case ACGJ_3 : //throw new InfraException("This controller is not supported:"+algoId); //
				return new ACGJ3(infra);
			case BEST_FIRST : //throw new InfraException("This controller is not supported:"+algoId); //
				return new BestFirstTLC(infra);
			case RELATIVE_LONGEST_QUEUE : //throw new InfraException("This controller is not supported:"+algoId); //
				return new RelativeLongestQueueTLC(infra);
			case RLD : //throw new InfraException("This controller is not supported:"+algoId); //
				return new RLDTLC(infra);
			case MOST_CARS : //throw new InfraException("This controller is not supported:"+algoId); //
				return new MostCarsTLC(infra);
			case LOCAL : //throw new InfraException("This controller is not supported:"+algoId); //
				return new LocalHillTLC(infra);
			case GENNEURAL : //throw new InfraException("This controller is not supported:"+algoId); //
				return new GenNeuralTLC(infra);
			case TC_1OPT : //throw new InfraException("This controller is not supported:"+algoId); //
				return new TC1TLCOpt(infra);
			case TC_2OPT : //throw new InfraException("This controller is not supported:"+algoId); //
				return new TC2TLCOpt(infra);
			case ACGJ_3_FV : //throw new InfraException("This controller is not supported:"+algoId); //
				return new ACGJ3FixedValue(infra);
			case RLD2: //throw new InfraException("This controller is not supported:"+algoId); //
				return new RLD2TLC(infra);
			case IATRACOS: //throw new InfraException("This controller is not supported:"+algoId); //
				return new IATRACOSTLC(infra);
			case MOREVTS_MARCHING: return new MorevtsMarchingTLC(infra);
			case MOREVTS_OPTIM: return new MorevtsOptimTLC(infra);
			case MOREVTS_COUNTING_CARS: return new MorevtsCountingCars(infra);
			case MOREVTS_COUNTING_CARS2: return new MorevtsCountingCars2(infra);
			case MOREVTS_SOTL_REQUEST: return new MorevtsSotlRequest(infra);
			case MOREVTS_SOTL_PHASE: return new MorevtsSotlPhase(infra);
			case MOREVTS_SOTL_PLATOON: return new MorevtsSotlPlatoon(infra);
			case MOREVTS_OPTIM_WETSTRAAT: return new MorevtsOptimWetstraatTLC(infra);
			case MOREVTS_MARCHING_WETSTRAAT: return new MorevtsMarchingWetstraatTLC(infra);
			case MOREVTS_SOTL_PLATOON2: return new MorevtsSotlPlatoon2(infra);
			case MOREVTS_OPTIM_LONGCLEAR: return new MorevtsOptimLongClear(infra);
			case CU_OPTIM: return new BroadwayOptim(infra);
			case CU_SOTL_P: return new BroadwaySotlPlatoon(infra);
			case CU_COFIELDS: return new BroadwayCoFields(infra);
			case CU_WIRELESS_SENSOR: return new BroadwayWirelessSensor(infra);
			case CU_TC1: return new BroadwayTC1(infra);
			case BASIC_TLC: return new BasicTLC(infra);
			case HALUK_1: return new TLCHaluk(infra);
		}
	   	throw new InfraException
    			("The TLCFactory can't make TLC's of type "+algoId);
	}
  
}  
